package ru.amse.tsyganov.jumleditor.editor;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Canvas;

import ru.amse.tsyganov.jumleditor.commands.Command;
import ru.amse.tsyganov.jumleditor.commands.CommandFactory;
import ru.amse.tsyganov.jumleditor.commands.ViewsManager;
import ru.amse.tsyganov.jumleditor.model.ActivityGraph;
import ru.amse.tsyganov.jumleditor.model.State;
import ru.amse.tsyganov.jumleditor.model.Transition;
import ru.amse.tsyganov.jumleditor.view.ActivityGraphView;
import ru.amse.tsyganov.jumleditor.view.Line;
import ru.amse.tsyganov.jumleditor.view.StateView;
import ru.amse.tsyganov.jumleditor.view.TransitionDraughtsman;
import ru.amse.tsyganov.jumleditor.view.TransitionView;
import ru.amse.tsyganov.jumleditor.view.ViewElementFactory;

public class AddTransitionMode extends EditorMode {

	public static final AddTransitionMode instance = new AddTransitionMode();
	
	private final Cursor cursorOverSpace;
	private final Cursor cursorOverFigure;
	
	private ViewsManager viewsManager;
	private ActivityGraphView<ActivityGraph> activityGraphView;
	private Canvas canvas;
	private Cursor currentCursor;
	
	private StateView<? extends State> sourceState;
	private StateView<? extends State> targetState;
	
	private int currentX;
	private int currentY;
	
	private AddTransitionMode() {
		cursorOverSpace = new Cursor(null, SWT.CURSOR_NO);
		cursorOverFigure = new Cursor(null, SWT.CURSOR_ARROW);
		
		currentCursor = cursorOverSpace;
	}
	
	public void init(
			ViewsManager viewsManager,
			ActivityGraphView<ActivityGraph> activityGraphView,
			Canvas canvas) {
		
		this.viewsManager = viewsManager;
		this.activityGraphView = activityGraphView;
		this.canvas = canvas;
	}
	
	@Override
	public void setCursor() {
		canvas.setCursor(currentCursor);
	}

	@Override
	public void mouseDoubleClick(MouseEvent e) {
		checkState();
	}

	@Override
	public void mouseDown(MouseEvent e) {
		checkState();
		
		sourceState = EditorUtil.getStateView(e.x, e.y);
		targetState = null;
		
		canvas.redraw();
	}

	@Override
	public void mouseMove(MouseEvent e) {
		checkState();
		
		currentX = e.x;
		currentY = e.y;
		
		targetState = EditorUtil.getStateView(e.x, e.y);
		
		if (targetState != null) {
			currentCursor = cursorOverFigure;
		} else {
			currentCursor = cursorOverSpace;
		}
		setCursor();
		
		canvas.redraw();
	}

	@Override
	public void mouseUp(MouseEvent e) {
		checkState();
		
		if (targetState != null) {
			assert sourceState != null;
			
			TransitionView<Transition> transitionView = 
				ViewElementFactory.factory.createTransitionView(
						sourceState.getModel().getStateVertex(), 
						targetState.getModel().getStateVertex());
			
			Command newTransitionCommand = 
				CommandFactory.createNewTransitionCommand(
					transitionView);
									
			viewsManager.executeCommand(newTransitionCommand);
		}
		
		sourceState = null;
		targetState = null;
		
		canvas.redraw();
	}

	@Override
	public void paintControl(PaintEvent e) {
		if (sourceState != null) {
			if (sourceState.getRectangle().contains(currentX, currentY)) {
				return;
			}
			GC gc = e.gc;
			
			if (targetState != null) {
				Line line = TransitionDraughtsman.getLine(
						sourceState.getRectangle(), 
						targetState.getRectangle());
				TransitionDraughtsman.drawArrowedLine(gc, line, false);
			} else {
				Line line = TransitionDraughtsman.getLine(
						new Point(currentX, currentY),
						sourceState.getRectangle());
				TransitionDraughtsman.drawArrowedLine(gc, line, false);
				sourceState.paint(gc);
			}
			gc.setLineStyle(SWT.LINE_SOLID);
		} 
	}

	private void checkState() {
		if (viewsManager == null ||
				activityGraphView == null ||
				canvas == null) {
			
			throw new IllegalStateException();
		}
	}

	@Override
	public void keyPressed(KeyEvent e) {	
	}

	@Override
	public void keyReleased(KeyEvent e) {
		// TODO Auto-generated method stub
		
	}
}
